feat(realtime): land LiveKit dead code + LK-based subscribe (PR 2 of 3)#138
feat(realtime): land LiveKit dead code + LK-based subscribe (PR 2 of 3)#138VerioN1 wants to merge 1 commit into
Conversation
Brings in the LiveKit transport layer as importable-but-mostly-unwired code,
and rewires the subscribe path onto it. Publish (createRealTimeClient) is
untouched and still goes through the existing aiortc WebRTCManager — the
final swap happens in PR 3 (current alon/livekit-prod HEAD).
What lands:
- New modules: stream-session, signaling-channel, media-channel,
remote-stream-exposure, observability/livekit-stats-provider,
realtime/config-realtime
- New utils: utils/media (imageToBase64), utils/platform
- RealtimeObservability gains setLiveKitRoom() that wires a LiveKit-room
stats provider into the same stats pipeline introduced in PR 1
- types.ts becomes a superset: keeps every aiortc message type (still
consumed by webrtc-connection/manager) and adds LK message + domain types
(LiveKitJoin/RoomInfo, QueuePosition, ConnectionStatus, SessionStarted,
InitialState, ServerError, ImageSetOptions, ...)
- subscribe-client.ts is rewritten onto livekit-client + RealtimeObservability
with the new room_name token format (was sid/ip/port). The aiortc-form
encoder/decoder used by the publish path's subscribeToken is inlined into
realtime/client.ts so it dies cleanly when client.ts is rewritten in PR 3
- createDecartClient now exposes realtime.{connect, subscribe} where
subscribe comes from createRealTimeSubscribeClient
- Adds livekit-client@^2 to packages/sdk deps
Notes for PR 3:
- Logger default stays noopLogger (flip to createConsoleLogger("info") in PR 3)
- diagnostics.ts keeps the LK-incompatible event types (IceCandidateEvent,
IceStateEvent, PeerConnectionStateEvent, SignalingStateEvent,
SelectedCandidatePairEvent) because aiortc publish still emits them; PR 3
drops them along with aiortc
- New tests added: realtime-observability-unit.test.ts and
realtime.unit.test.ts (set() block excluded — depends on PR 3's methods.ts)
- A few unit.test.ts assertions adjusted to the new shape: removed the old
aiortc-form Subscribe Token round-trip block (covered by the new room_name
tests in realtime.unit.test.ts), inlined the legacy decoder in the
session_id-populates-subscribeToken test, and removed the
TelemetryReporter "warns on non-2xx" test (telemetry is now silent on
non-2xx by design)
Validation: typecheck clean, 217/217 tests pass, biome check clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
commit: |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a7a41d2. Configure here.
| * totalInterFrameDelay + totalSquaredInterFrameDelay. | ||
| */ | ||
| interFrameDelayStdDevMs: number | null; | ||
| interFrameDelayVarianceMs: number | null; |
There was a problem hiding this comment.
Field named "variance" actually computes standard deviation
Medium Severity
The field interFrameDelayStdDevMs was renamed to interFrameDelayVarianceMs, but the computation still calculates the standard deviation (square root of variance), not variance. The comment even still states "Report std-dev in ms." Consumers relying on this field as a variance value will get incorrect results — variance and standard deviation have different units and magnitudes (variance is in ms², std-dev is in ms).
Additional Locations (1)
Reviewed by Cursor Bugbot for commit a7a41d2. Configure here.
| return image; | ||
| } | ||
| return blobToBase64(image); | ||
| } |
There was a problem hiding this comment.
Duplicate blobToBase64 and imageToBase64 in two files
Low Severity
blobToBase64 and imageToBase64 in utils/media.ts are exact duplicates of the same functions in realtime/client.ts. The new utils/media.ts exports are not imported anywhere in the codebase — they are completely unused. While the PR description says these are shared utils, client.ts still uses its own inline copies.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit a7a41d2. Configure here.


Summary
Brings in the LiveKit transport layer as importable-but-mostly-unwired code, and rewires the subscribe path onto it. Publish (
createRealTimeClient) is untouched and still uses the existing aiortcWebRTCManager— the final swap happens in PR 3 (the currentalon/livekit-prodHEAD).This PR is structured so that every line either belongs to the LK transport (new files) or to a strictly additive change on the existing surface. Nothing aiortc was modified for the sake of giving this PR meaning.
What lands
stream-session.ts,signaling-channel.ts,media-channel.ts,remote-stream-exposure.ts,observability/livekit-stats-provider.ts,realtime/config-realtime.tsutils/media.ts(sharedimageToBase64),utils/platform.tsRealtimeObservabilitygainssetLiveKitRoom()that wires a LK-room stats provider into the same stats pipeline introduced in PR 1types.tsbecomes a superset:OfferMessage/AnswerMessage/IceCandidateMessage/ReadyMessage/SessionIdMessage/etc.) — still consumed bywebrtc-connection/webrtc-managerLiveKitJoinMessage,LiveKitRoomInfoMessage,QueuePosition/QueuePositionMessage,ConnectionStatus,SessionStarted,InitialState,ServerError,ImageSetOptions, …)subscribe-client.tsis rewritten ontolivekit-client+RealtimeObservabilitywith the newroom_nametoken format (wassid/ip/port). The aiortc-form encoder/decoder previously living here and used by the publish path'ssubscribeTokenis inlined intorealtime/client.tsso it dies cleanly whenclient.tsis rewritten in PR 3createDecartClientnow exposesrealtime.{ connect, subscribe }wheresubscribecomes fromcreateRealTimeSubscribeClientlivekit-client@^2topackages/sdkdepsIntentionally deferred to PR 3
noopLogger(PR 3 flips tocreateConsoleLogger(\"info\"))diagnostics.tskeeps the LK-incompatible event types (IceCandidateEvent,IceStateEvent,PeerConnectionStateEvent,SignalingStateEvent,SelectedCandidatePairEvent) because aiortc publish still emits them; PR 3 drops them along with aiortcclient.ts→StreamSession, deletion ofwebrtc-manager.ts/webrtc-connection.ts,methods.tsrewrite, aiortc tests removal)Tests
tests/realtime-observability-unit.test.tsandtests/realtime.unit.test.ts(theset()block from the LK branch is excluded — it depends on PR 3'smethods.ts)tests/unit.test.tsassertions adjusted to the new shape:room_nametests inrealtime.unit.test.ts)session_idpopulatessubscribeTokentestTelemetryReporter"warns on non-2xx" test (telemetry is now silent on non-2xx by design —.catch(() => {}))Test plan
pnpm typecheckcleanpnpm test— 217/217 passingpnpm exec biome check .cleancreateDecartClient().realtime.connect) still works against existing aiortc backendcreateDecartClient().realtime.subscribe) connects to a LK-backed/watch-streamtoken🤖 Generated with Claude Code
Note
Medium Risk
Replaces the realtime subscribe implementation and reshapes the public
realtimeAPI, which may break existing consumers and introduces a new LiveKit dependency plus new connection/telemetry behavior.Overview
Adds a new LiveKit-backed realtime stack (config, signaling/media channels, session orchestration, and a LiveKit stats adapter) and switches
subscribeto use it, including a newroom_name-based subscribe token and a/watch-stream/:roomcredential fetch.Updates the public SDK surface so
createDecartClient().realtimebecomes{ connect, subscribe }(splitting publish vs subscribe clients), expands realtime domain types, and centralizes realtime constants inREALTIME_CONFIG.Observability/telemetry is updated to support LiveKit rooms as a stats source, move hardcoded thresholds/intervals/URLs into config, and make telemetry reporting best-effort/silent on failures. New unit tests cover the LiveKit subscribe flow, signaling handshake/queue behavior, retry/reconnect orchestration, and the updated observability pipeline.
Reviewed by Cursor Bugbot for commit a7a41d2. Bugbot is set up for automated code reviews on this repo. Configure here.